package com.david.viewtest.view

import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.core.view.marginBottom
import androidx.core.view.marginEnd
import androidx.core.view.marginStart
import androidx.core.view.marginTop
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import kotlin.math.abs

/**
 * 默认从第二个元素开始为侧滑menu，最后一个为deleteBtn（如果有）
 */
class SlideCellView(context: Context, attr: AttributeSet?) : FrameLayout(context, attr) {
    /**
     * 是否有删除按钮
     */
    private var hasDeleteBtn = true

    /**
     * 删除按钮是否需要二次确认，不需要时删除按钮点击会走menuBtnClickFunc回调
     */
    private var needDeleteBtnConfirm = true

    /**
     * 删除按钮二次确认文案
     */
    private var deleteBtnConfirmText: String? = "确认删除"


    /**
     * 删除按钮，默认为最后一个view，如果有则设置属性hasDeleteBtn为true
     */
    private var deleteBtn: TextView? = null

    /**
     * 删除按钮原始宽度（二次确认前宽度）
     */
    private var deleteBtnOriginWidth = 0

    /**
     * 普通menu按钮点击事件
     */
    var menuBtnClickFunc: ((View) -> Unit)? = null

    /**
     * 删除menu按钮点击事件
     */
    var confirmFirstClickFunc: (() -> Unit)? = null

    /**
     * 删除按钮二次确认事件
     */
    var confirmSecondClickFunc: (() -> Unit)? = null

    /**
     * 侧滑menu的总宽度
     */
    private var menuWidth = 0


    private val SLIDE_STATE_CLOSED = 0 //关闭状态
    private val SLIDE_STATE_OPEN = 1 //打开状态
    private val SLIDE_STATE_CONFIRM = 2 //二次确认状态

    /**
     * 当前item的状态：关闭、打开、删除二次确认
     */
    private var slideState = SLIDE_STATE_CLOSED //侧滑状态，关闭、打开、二次确认


    /**
     * item单击事件
     */
    var viewClickFunc: (() -> Unit)? = null

    /**
     * item长按事件
     */
    var viewLongClickFunc: (() -> Unit)? = null


    private var animTime = 200L

    /**
     * 用于触发长按事件的task
     */
    private var longClickTask = Runnable {
        closeMenuWithAnim {
            viewLongClickFunc?.invoke()
            Toast.makeText(context, "on item long clicked...", Toast.LENGTH_LONG).show()
        }
    }

    private fun initMenuListener() {
        if (needDeleteBtnConfirm) {
            for (index in 1 until childCount - 1) {
                getChildAt(index).setOnClickListener {
                    closeMenuWithAnim {
                        menuBtnClickFunc?.invoke(it)
                        Toast.makeText(context, (it as TextView).text, Toast.LENGTH_LONG).show()
                    }
                }
            }


            deleteBtn = getChildAt(childCount - 1) as TextView
            deleteBtn?.setOnClickListener {
                if (slideState != SLIDE_STATE_CONFIRM) {
                    slideState = SLIDE_STATE_CONFIRM

                    deleteBtn?.updateLayoutParams<MarginLayoutParams> { width = menuWidth }

                    confirmFirstClickFunc?.invoke()

                    deleteBtn?.text = deleteBtnConfirmText
                } else {
                    closeMenuWithAnim {
                        confirmSecondClickFunc?.invoke()

                        Toast.makeText(context, "delete btn clicked。。。", Toast.LENGTH_LONG).show()
                    }
                }
            }
        } else {
            //没有二次确认时删除按钮回调默认走menuBtnClickFunc
            for (index in 1 until childCount) {
                getChildAt(index).setOnClickListener {
                    closeMenuWithAnim {
                        menuBtnClickFunc?.invoke(it)
                        Toast.makeText(context, (it as TextView).text, Toast.LENGTH_LONG).show()
                    }
                }
            }
        }
    }


    //放置到recyclerview中时添加ScrollListener用于关闭menu
    private var listenerAdded = false
    private fun initListener() {
        if (!listenerAdded) {
            if (parent is RecyclerView) {
                (parent as RecyclerView).addOnScrollListener(object : OnScrollListener() {
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        super.onScrollStateChanged(recyclerView, newState)
                        closeMenuWithAnim()
                    }
                })
            }

            initMenuListener()

            listenerAdded = true
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        initListener()

        if (menuWidth == 0) {
            for (index in 1 until childCount) {
                menuWidth += getChildAt(index).measuredWidth
            }
        }

        if (hasDeleteBtn && deleteBtnOriginWidth == 0) {
            deleteBtnOriginWidth = getChildAt(childCount - 1).measuredWidth
        }
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        //super.onLayout(changed, left, top, right, bottom)

        val count = childCount

        var startLeft = measuredWidth

        getChildAt(0).layout(getChildAt(0).marginStart, getChildAt(0).marginTop, measuredWidth - getChildAt(0).marginEnd, measuredHeight - getChildAt(0).marginBottom)

        if (needDeleteBtnConfirm) {
            deleteBtn = getChildAt(count - 1) as TextView
            if (slideState != SLIDE_STATE_CONFIRM) {
                for (index in 1 until childCount - 1) {
                    getChildAt(index).layout(startLeft, 0,
                        (startLeft + getChildAt(index).measuredWidth), height)

                    startLeft += getChildAt(index).measuredWidth
                }
            }

            deleteBtn?.layout(measuredWidth + menuWidth - (deleteBtn?.measuredWidth ?: 0), 0,
                (measuredWidth + menuWidth), height)
        } else {
            for (index in 1 until childCount) {
                getChildAt(index).layout(startLeft, 0,
                    (startLeft + getChildAt(index).measuredWidth), height)

                startLeft += getChildAt(index).measuredWidth
            }
        }
    }

    private var touchDownX: Float = 0f
    private var touchDownY: Float = 0f

    private var onTouch = false
    private var distance = 0f

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> {
                touchDownX = ev.x
                touchDownY = ev.y

                lastTouchTime = System.currentTimeMillis()
            }

            MotionEvent.ACTION_MOVE -> {
                if (!onTouch) {
                    onTouch = abs(ev.x - touchDownX) > abs(ev.y - touchDownY)

                    return onTouch

                }
            }
            //MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {}
        }
        return super.onInterceptTouchEvent(ev)
    }

    private var lastX = 0

    private var lastPositionX = 0

    private var lastTouchTime = 0L

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> {
                super.onTouchEvent(ev)

                if (viewLongClickFunc != null) {
                    postDelayed(longClickTask, 1000)
                }
                return true
            }

            MotionEvent.ACTION_MOVE -> {
                if (!onTouch) {
                    onTouch = abs(ev.x - touchDownX) > 30 && abs(ev.x - touchDownX) > abs(ev.y - touchDownY)

                    if (parent is RecyclerView) { //放在列表中时打开当前item关闭其他item，需要同时存在时注释即可
                        val recyclerView = parent as RecyclerView
                        for (index in 0 until recyclerView.childCount) {
                            val item = recyclerView.getChildAt(index) as SlideCellView
                            if (item != this) {
                                item.closeMenuWithAnim()
                            }
                        }
                    }


                    if (viewLongClickFunc != null) {
                        removeCallbacks(longClickTask)
                    }
                }

                if (onTouch) {
                    parent.requestDisallowInterceptTouchEvent(true);

                    //Log.e("move", "onTouchEvent move: ${(ev.x - touchDownX).toString()}")
                    distance = ev.x - touchDownX

                    lastPositionX = -(ev.x - touchDownX).toInt() + lastX
                    if (lastPositionX < 0) { //滑动到最左边了
                        lastPositionX = 0
                    } else if (lastPositionX > menuWidth) {
                        lastPositionX = menuWidth
                    }
                    scrollTo(lastPositionX, 0)

                    return true
                }
            }

            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                if (onTouch) {
                    val distance = (ev.x - touchDownX).toInt()

                    if (distance < -100) { //向左滑动了一段距离
                        lastX = menuWidth

                        slideState = SLIDE_STATE_OPEN
                    } else if (distance > 100) { //向右滑动了一段距离
                        lastX = 0

                        postDelayed({
                            resetState()
                            postInvalidate()
                        }, 200)
                    }

                    startAnim(lastPositionX, lastX)


                    lastPositionX = lastX
                    //
                    //    //                    记录上次滑动的位置
                    //    //                    lastX -= distance
                    onTouch = false
                    return true
                } else if (ev.action == MotionEvent.ACTION_UP && System.currentTimeMillis() - lastTouchTime < 100) {
                    closeMenuWithAnim {
                        if (viewClickFunc != null) {
                            //Log.e("move", "click: ${System.currentTimeMillis() - lastTouchTime}")
                            viewClickFunc?.invoke()
                        }
                        Toast.makeText(context, "list item clicked。。。", Toast.LENGTH_LONG).show()
                    }
                }


                if (viewLongClickFunc != null) {
                    removeCallbacks(longClickTask)
                }
            }
        }
        return super.onTouchEvent(ev)
    }

    private var animStartX = 0
    private var animator: ValueAnimator? = null

    private fun startAnim(start: Int, end: Int) {
        animStartX = start
        animator = ValueAnimator.ofInt(start, end)
        animator?.duration = animTime
        animator?.addUpdateListener { anim ->
            scrollTo(anim.animatedValue as Int, 0)
        }

        animator?.start()
    }


    fun closeMenuWithAnim(animEndFunc: (() -> Unit)? = null) {
        if (slideState != SLIDE_STATE_CLOSED) {
            animator?.cancel()

            lastX = 0
            startAnim(scrollX, lastX)


            postDelayed({
                resetState()

                animEndFunc?.invoke()
            }, animTime)
        } else {
            animEndFunc?.invoke()
        }
    }

    /**
     * 无动画的关闭menu，在列表bindView方法处调用防止view复用导致的动画问题
     */
    fun closeMenuWithOutAnim() {
        if (slideState != SLIDE_STATE_CLOSED) {
            animator?.cancel()

            lastX = 0
            scrollTo(lastX, 0)

            resetState()
        }
    }

    private fun resetState() {
        if (slideState == SLIDE_STATE_CONFIRM) {
            deleteBtn?.updateLayoutParams<MarginLayoutParams> { width = deleteBtnOriginWidth }

            deleteBtn?.text = "删除"
        }
        slideState = SLIDE_STATE_CLOSED
    }
}